#ifndef __BUTTON_H__
#define __BUTTON_H__

#include "soc/soc_gpio.h"
#include "plat/nonecopyable.h"
#include "thirdparty/MultiButton/multi_button.h"
#include <map>
#include "os/timer.h"
#include "device_def.h"

#define BUTTON_DEV_MAX_COUNT 30
#define BUTTON_DEV_TICK_MS 5

/// @brief 按键
class ButtonDevice : public ICanMgrDevice<ButtonDevice, int, BUTTON_DEV_MAX_COUNT>
{
public:
    enum class ButtonAction
    {
        None = 0,
        Down,
        Up,
        DownLong,
        DoubleClick
    };

    using BUTTON_EVENT = std::function<void(ButtonDevice &button, ButtonAction action)>;

public:
    explicit ButtonDevice();
    explicit ButtonDevice(int id, GpioPortPin portPin, int activeLevel = 0);
    explicit ButtonDevice(int id, const std::string &name, GpioPortPin portPin, int activeLevel = 0);
    virtual ~ButtonDevice();

public:
    void SetInfo(int id, GpioPortPin portPin, int activeLevel = 0);
    void SetInfo(int id, const std::string &name, GpioPortPin portPin, int activeLevel = 0);

    int GetId();
    std::string GetName();
    GpioPortPin GetPortPin();
    int GetActiveLevel();

    bool GetDownState();
    bool GetLongDownState();

    void Start();
    void Stop();

    void SetEventListener(const BUTTON_EVENT&& func);

    static void SetEventListenerAny(const BUTTON_EVENT&& func);
    
public:
    static void StartAll();
    static void StopAll();

public: //框架使用
    uint8_t ReadInputLevel();
    void RaiseEventCallBack(ButtonAction action);

private:
    void __AddToDeviceList();
    void __Init();

private:
    std::string m_name;
    uint8_t m_id = -1;
    uint8_t m_activeLevel;
    bool m_isInit = false;

    GpioPortPin m_portPin;
    Button m_button;

    //状态
    bool m_isDown = false;
    bool m_isLongDown = false;

    BUTTON_EVENT m_eventFunc = nullptr;
    static BUTTON_EVENT m_eventFuncAny;
};

#endif // __BUTTON_H__